
#include "2048game.h"
#include "bmp.h"
#include "lcd.h"
#include "touch.h"

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <time.h>

//保存游戏的数据 
int game[4][4] = {0};

int score = 0;          //游戏得分
int MAX_SCORE = 0;      //最高分
int LEVEL = 2048;       //游戏难易程度

//刷新游戏界面 
void refresh()
{
    int i,j;
    for( i=0; i<4; i++ )
    {
        for( j=0; j<4; j++ )
        {
            printf("%d\t", game[i][j] );

            //合成图片的名字 0.bmp / 2.bmp / 4.bmp / ... 
            char buf[32] = {0};
            snprintf( buf, 32, "%d%s", game[i][j], ".bmp" );

            //显示 ---> 4x4矩阵
            show_bmp( j*150, i*150, buf );
        }
        putchar('\n');
    }
    putchar('\n');

    //实时分数 和 最高分 
    //...
}


//在随机的位置上，生成随机的2或4 
void position()
{
    //1.判断是否有空白的位置(0)
    int flag = 0;       //标志位：0没有空白，1有空白位置
    int i,j;
    for( i=0; i<4 && flag == 0; i++ )
    {
        for( j=0; j<4; j++ )
        {
            if( game[i][j] == 0 )
            {
                flag = 1;   //有空白位置
                break;
            }
        }
    }

    //2.生成随机的2或4 
    int rand_value = ( rand()%2 + 1 ) * 2;  
        // int rand_value = rand()%2 ? 4 : 2;

    //3.生成随机的位置 
    while( flag )
    {
        int i = rand() % 4;
        int j = rand() % 4;

        if( game[i][j] == 0 )   //只能在空白的位置(0)，去生成随机数
        {
            game[i][j] = rand_value;
            break;
        }
    }

    //4.刷新游戏界面
    refresh();
}


//判断能否上移：1能够移动，0不能移动 
int judge_up()
{
    int i,j;
    for( j=0; j<4; j++ )
    {
        for( i=0; i<3; i++ )
        {
            //情况一：相邻的两个元素值相等，且都不为0，数据可以合并
            if( game[i][j] == game[i+1][j] && game[i][j] != 0 )
            {
                return 1;       //可以合并
            }
            //情况二：相邻的两个元素值不相等，但是前一个元素的值为0（空白位置）
            if( game[i][j] != game[i+1][j] && game[i][j] == 0 )
            {
                return 1;       //可以移动
            }
        }
    }
    return 0;   //不能移动
}

int judge_down()
{
	int i,j;
    for( j=0; j<4; j++ )
    {
        for( i=3; i>0; i-- )
        {
            //情况一：相邻的两个元素值相等，且都不为0，数据可以合并
            if( game[i][j] == game[i-1][j] && game[i][j] != 0 )
            {
                return 1;       //可以合并
            }
            //情况二：相邻的两个元素值不相等，但是前一个元素的值为0（空白位置）
            if( game[i][j] != game[i-1][j] && game[i][j] == 0 )
            {
                return 1;       //可以移动
            }
        }
    }
    return 0;   //不能移动
}

//判断能否左移：1能够移动，0不能移动
int judge_left()
{
    int i,j;
    for( i=0; i<4; i++ )
    {
        for( j=0; j<3; j++ )
        {
            //情况一：相邻的两个元素值相等，且都不为0，数据可以合并
            if( game[i][j] == game[i][j+1] && game[i][j] != 0 )
            {
                return 1;       //可以合并
            }
            //情况二：相邻的两个元素值不相等，但是前一个元素的值为0（空白位置）
            if( game[i][j] != game[i][j+1] && game[i][j] == 0 )
            {
                return 1;       //可以移动
            }
        }
    }
    return 0;   //不能移动
}

int judge_right()
{
	int i,j;
    for( i=0; i<4; i++ )
    {
        for( j=3; j>0; j-- )
        {
            //情况一：相邻的两个元素值相等，且都不为0，数据可以合并
            if( game[i][j] == game[i][j-1] && game[i][j] != 0 )
            {
                return 1;       //可以合并
            }
            //情况二：相邻的两个元素值不相等，但是前一个元素的值为0（空白位置）
            if( game[i][j] != game[i][j-1] && game[i][j] == 0 )
            {
                return 1;       //可以移动
            }
        }
    }
    return 0;   //不能移动
}

//判断所有的方向是否能够移动
int judge_move( int fx )
{
    //1.判断所有的方向是否能够移动
    int count = 0;
    count += judge_up();
    count += judge_down();
    count += judge_left();
    count += judge_right();

    if( count == 0 )
    {
        //所有的方向 都不能移动 ---> 游戏失败 
        return 3;
    }

    //2.判断当前的单个方向fx能否移动
    count = 0;
    switch( fx )
    {
        case 1 : count = judge_up(); break;
        case 2 : count = judge_down(); break;
        case 3 : count = judge_left(); break;
        case 4 : count = judge_right(); break;
    }

    if( count == 0 )
    {
        //当前单个方向fx不能移动 ---> 无效滑动 
        return 4;
    }
    else 
    {
        //可以移动的
        return 1;   //游戏继续 
    }

}


//上移
void move_up()
{
    //1.先合并
    int i,j,k;
    for( j=0; j<4; j++ )
    {
        for( i=0; i<3; i++ )
        {
            if( game[i][j] != 0 )
            {
                for( k=i+1; k<4; k++ )  //k表示game[i][j]元素的下一个 
                {
                    if( game[i][j] != game[k][j] && game[k][j] != 0 )
                    {
                        //相邻的两个元素不相等，且都不为0，不能合并
                        break;
                    }
                    else if( game[i][j] != game[k][j] && game[k][j] == 0) 
                    {
                        //相邻的两个元素不相等，但是 后一个元素为0，则应该继续找k的下一个
                        continue;
                    }
                    else if( game[i][j] == game[k][j] )
                    {
                        //相邻的两个元素相等，且不为0，则可以合并
                        game[i][j] = game[i][j] * 2;
                        game[k][j] = 0;

                        //计算得分
                        score = score + game[i][j]; 
                        if( score > MAX_SCORE )
                        {
                            MAX_SCORE = score;  //更新最大值
                        }

                        break;
                    }
                }
            }
        }
    }

    //2.再移动 
    for( j=0; j<4; j++  )
    {
        for( i=0; i<3; i++)
        {
            if( game[i][j] == 0 )       //前一个为0
            {
                for( k=i+1; k<4; k++ )
                {
                    if( game[k][j] != 0 )   //后一个不为0
                    {
                        //移动
                        game[i][j] = game[k][j];
                        game[k][j] = 0;

                        break;
                    }
                }
            }
        }
    }
}

void move_down()
{
	//1.先合并
    int i,j,k;
    for( j=0; j<4; j++ )
    {
        for( i=3; i>0; i-- )
        {
            if( game[i][j] != 0 )
            {
                for( k=i-1; k>=0; k-- )  //k表示game[i][j]元素的下一个 
                {
                    if( game[i][j] != game[k][j] && game[k][j] != 0 )
                    {
                        //相邻的两个元素不相等，且都不为0，不能合并
                        break;
                    }
                    else if( game[i][j] != game[k][j] && game[k][j] == 0) 
                    {
                        //相邻的两个元素不相等，但是 后一个元素为0，则应该继续找k的下一个
                        continue;
                    }
                    else if( game[i][j] == game[k][j] )
                    {
                        //相邻的两个元素相等，且不为0，则可以合并
                        game[i][j] = game[i][j] * 2;
                        game[k][j] = 0;

                        //计算得分
                        score = score + game[i][j]; 
                        if( score > MAX_SCORE )
                        {
                            MAX_SCORE = score;  //更新最大值
                        }

                        break;
                    }
                }
            }
        }
    }

    //2.再移动 
    for( j=0; j<4; j++  )
    {
        for( i=3; i>0; i-- )
        {
            if( game[i][j] == 0 )       //前一个为0
            {
                for( k=i-1; k>=0; k-- )
                {
                    if( game[k][j] != 0 )   //后一个不为0
                    {
                        //移动
                        game[i][j] = game[k][j];
                        game[k][j] = 0;

                        break;
                    }
                }
            }
        }
    }
}

//左移
void move_left()
{
    //1.先合并
    int i,j,k;
    for( i=0; i<4; i++ )
    {
        for( j=0; j<3; j++ )
        {
            if( game[i][j] != 0 )
            {
                for( k=j+1; k<4; k++ )  //k表示game[i][j]元素的下一个 
                {
                    if( game[i][j] != game[i][k] && game[i][k] != 0 )
                    {
                        //相邻的两个元素不相等，且都不为0，不能合并
                        break;
                    }
                    else if( game[i][j] != game[i][k] && game[i][k] == 0) 
                    {
                        //相邻的两个元素不相等，但是 后一个元素为0，则应该继续找k的下一个
                        continue;
                    }
                    else if( game[i][j] == game[i][k] )
                    {
                        //相邻的两个元素相等，且不为0，则可以合并
                        game[i][j] = game[i][j] * 2;
                        game[i][k] = 0;

                        //计算得分
                        score = score + game[i][j]; 
                        if( score > MAX_SCORE )
                        {
                            MAX_SCORE = score;  //更新最大值
                        }

                        break;
                    }
                }
            }
        }
    }

    //2.再移动 
    for( i=0; i<4; i++ )
    {
        for( j=0; j<3; j++ )
        {
            if( game[i][j] == 0 )       //前一个为0
            {
                for( k=j+1; k<4; k++ )
                {
                    if( game[i][k] != 0 )   //后一个不为0
                    {
                        //移动
                        game[i][j] = game[i][k];
                        game[i][k] = 0;

                        break;
                    }
                }
            }
        }
    }
}

void move_right()
{
	//1.先合并
    int i,j,k;
    for( i=0; i<4; i++ )
    {
        for( j=3; j>0; j-- )
        {
            if( game[i][j] != 0 )
            {
                for( k=j-1; k>=0; k-- )  //k表示game[i][j]元素的下一个 
                {
                    if( game[i][j] != game[i][k] && game[i][k] != 0 )
                    {
                        //相邻的两个元素不相等，且都不为0，不能合并
                        break;
                    }
                    else if( game[i][j] != game[i][k] && game[i][k] == 0) 
                    {
                        //相邻的两个元素不相等，但是 后一个元素为0，则应该继续找k的下一个
                        continue;
                    }
                    else if( game[i][j] == game[i][k] )
                    {
                        //相邻的两个元素相等，且不为0，则可以合并
                        game[i][j] = game[i][j] * 2;
                        game[i][k] = 0;

                        //计算得分
                        score = score + game[i][j]; 
                        if( score > MAX_SCORE )
                        {
                            MAX_SCORE = score;  //更新最大值
                        }

                        break;
                    }
                }
            }
        }
    }

    //2.再移动 
    for( i=0; i<4; i++ )
    {
        for( j=3; j>0; j-- )
        {
            if( game[i][j] == 0 )       //前一个为0
            {
                for( k=j-1; k>=0; k-- )
                {
                    if( game[i][k] != 0 )   //后一个不为0
                    {
                        //移动
                        game[i][j] = game[i][k];
                        game[i][k] = 0;

                        break;
                    }
                }
            }
        }
    }

}

//数据合并和移动
void move( int fx )
{
    //1.根据用户的滑动方向，进行游戏数据的合并和移动
    switch( fx )
    {
        case 1 : move_up(); break;
        case 2 : move_down(); break;
        case 3 : move_left(); break;
        case 4 : move_right(); break;
    }

    //2.刷新游戏界面
    refresh();
}


//判断游戏是否成功--->出现2048
int is_win()
{
    int i,j;
    for( i=0; i<4; i++ )
    {
        for( j=0; j<4; j++ )
        {
            if( game[i][j] == LEVEL )       // LEVEL => 2048 
            {
                return 2;   //游戏成功
            }
        }
    }
    return 0;   
}


//2048游戏
int my_2048game()
{
    //0.设置时间种子
    srand( time(NULL) );


    //1.初始化游戏，并刷新界面 
    int i,j;
    for( i=0; i<4; i++ )
    {
        for( j=0; j<4; j++ )
        {
            game[i][j] = 0;
        }
    }
    score = 0;
    refresh();

    sleep( 2 );

    //在随机的位置上，生成随机的2或4
    position();
    position();

    //开始游戏
    while( 1 )
    {
        //3.获取用户手指滑动的方向
        int fx = get_direction();
        printf("fx = %d\n", fx );

        //4.判断所有的方向是否能够移动
        int flag = judge_move( fx );

        if( flag == 1 )     //游戏继续 
        {
            //进行数据的合并和移动 
            move( fx );

            //判断游戏是否成功--> 出现了2048 
            if( is_win() == 2 )
            {
                //游戏成功的处理 （重新开始/结束游戏）

                printf("Victory !\n");
                break;
            }

            //再次生成新的一个随机的2或4
            position();

        }
        else if( flag == 3 )    //游戏失败 
        {
            //游戏失败的处理 （重新开始/结束游戏）

            printf("Game Over !\n");
            break;
        }
        else if( flag == 4 )    //无效滑动 
        {
            continue;
        }
    }
}

